from loguru import logger
from pymongo import MongoClient
from pymongo.errors import ConnectionFailure
from app.settings.base import database, all_permission_key, super_administrator, all_permission
from app.globals.uuidTool import getuuId
import traceback, sys
from . import dbSynPosUser, collectionUserList, collectionUserRoleList, dbSynPosServer, collectionServerList
'''
从pymongo3.0版本开始，MongoClient的构造函数就不会再阻塞等待MongoDB连接的建立，
即使连接不上也不会上报ConnectionFailure
用户提交的资格证书（估计是用户名密码或者cert证书）是错误的也不会上报ConfigurationError。
相反，构造函数会立即返回并在后台线程中加载处理连接数据的进程。如果想确认返回的client是否真实可用，可以如下操作:
client.admin.command('ismaster')

connectTimeoutMS，连接mongo的超时机制， 默认20s
serverSelectionTimeoutMS，连接database的超时机制， 默认30s

参考：https://www.jianshu.com/p/d9918b0a3ebc
手册：https://pymongo.readthedocs.io/en/stable/index.html
'''


class MongoError(RuntimeError):
    def __init__(self, errMsg):
        self.errMsg = errMsg

    def data(self, errDetails):
        self.errDetails = errDetails
        return self


ErrMongoClient = MongoError('操作mongo异常')

mongo_client_instance = None

def mongo_client():
    global mongo_client_instance
    if mongo_client_instance is None:
        try:
            # mongo_client_instance = MongoClient('mongodb://admin:123456@localhost:27017/')
            dbHost = database['host']
            logger.info(f'尝试连接数据库, dbhost={dbHost}')
            dbPort = database['port']
            dbUsername = database['username']
            dbPassword = database['password']
            mongo_client_instance = MongoClient(
                            host=dbHost, 
                            port=dbPort, 
                            username=dbUsername, 
                            password=dbPassword, 
                            serverSelectionTimeoutMS=5000*6)
            mongo_client_instance.admin.command('ismaster')
            # 1. 往服务列表插入系统可导出的所有权限
            collectionServer = mongo_client_instance[dbSynPosServer][collectionServerList]
            res = collectionServer.find_one()
            if res is None:
                post = {
                    'schoolName': '新中新大学',
                    'schoolLogo': '',
                    'rolePower': all_permission
                }
                collectionServer.insert_one(post)              

            # 2. 创建超级管理员角色 + 创建/更新超级管理员角色权限
            cond = {'roleName': super_administrator}
            collection = mongo_client_instance[dbSynPosUser][collectionUserRoleList]
            res = collection.find_one(cond)
            roleId = getuuId()
            if res is None:
                data = {
                    'roleId': roleId,
                    'roleName': super_administrator,
                    'rolePower': all_permission_key
                }
                collection.insert_one(data)
            else:
                res['rolePower'] = all_permission_key
                collection.update(cond, res)
            # 3. 创建超级管理员用户
            collection = mongo_client_instance[dbSynPosUser][collectionUserList]
            res = collection.find_one({'userName': 'synjones'})
            userId = getuuId()
            if res is None:
                data = {
                    'userId': userId,
                    'userName': 'synjones',
                    'userPwd': '4EE644549B75BEF07E5C04BEB0B43376', # same2021--md5--md5
                    'userRoleId': roleId
                }
                collection.insert_one(data)

            collection = mongo_client_instance[dbSynPosUser][collectionUserList]
            res = collection.find_one({'userName': 'root_admin_synjones'})
            userId = getuuId()
            if res is None:
                data = {
                    'userId': userId,
                    'userName': 'root_admin_synjones',
                    'userPwd': '9C6B80F22FCAB3867C3F3EDAACAF0CC9', # same
                    'userRoleId': roleId
                }
                collection.insert_one(data)
            logger.info(f'数据库连接成功')
        except ConnectionFailure:
            logger.error(f'数据库连接异常, 程序退出')
            sys.exit(0)
        except Exception as e:
            logger.error(f'数据库初次连接异常, 程序退出:{str(e)},traceback={traceback.format_exc()}')
            sys.exit(0)


'''
    1. pymongo内部做了断线重连处理，无需外部处理
    2. MongoClient实例调用其他接口时，内部会断线重连处理，如果连接不上会报异常
'''
def get_mongo_client():
    return mongo_client_instance